#include "protocol.hpp"
#include "Socket.hpp"
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <ctime>
#include <cstdlib>
using namespace std;


int main(int argc, char* args[]) {
    if (argc != 3) {
        cout << "Usage:\n" << args[0] << "server_ip server_port\n" << endl;
        return 0;
    }
    string serverip = args[1];
    uint16_t serverport = stoi(args[2]);
    Net_Work::Socket* s = new Net_Work::TcpSocket();
    if (!s->BuildConnectSocket(serverip, serverport)) {
        cerr << "connect " << serverip << ": " << serverport << " error, error code: " << errno << "error string: " << \
        strerror(errno) << endl;
    }
    // 连接成功
    cout << "connect " << serverip << ": " << serverport << " success!" << endl;
    // string message = "hello world!!";
    // write(s->GetSockFd(), message.c_str(), message.size());
    unique_ptr<Protocol::Factory> fac = unique_ptr<Protocol::Factory>(new Protocol::Factory());
    // Request* req = new Request(10, 20, '+');
    srand(time(nullptr) ^ pthread_self() ^ getpid()); // 种一颗随机数种子
    const string opers = "+-*/%^&=";
    while (true) {
        // 1、构建一个请求
        int x = rand() % 100;
        usleep(rand() % 7777);
        int y = rand() % 100;
        usleep(rand() % 8888);
        char op = opers[rand() % opers.size()];
        shared_ptr<Protocol::Request> req = fac->BuildRequest(x, y, op);

        // 2、对请求进行序列化
        string requeststr;
        req->serialize(&requeststr);

        // 3、 添加自描述报头
        requeststr = Protocol::Encode(requeststr);

        // 4、发送请求
        s->Send(requeststr);

        while (true) {
            // 5、读取响应
            string responsestr;
            s->Recv(&responsestr, 1024);

            // 6、对报文进行解析
            string response;
            if (!Protocol::Decode(responsestr, &response)) {
                continue;
            }
            // 7、反序列化
            auto resp = fac->BuildResponse();
            resp->deserialize(response);

            // 8、得到了计算结果
            cout << req->ToString() << "==" << resp->GetResult() << "[" << resp->GetCode() << "]" << endl;

        }


    }

    s->CloseSockfd();
        
        
    return 0;
}